home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wtabview.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-28  |  17.5 KB  |  791 lines

  1.  
  2. #include "WINGsP.h"
  3.  
  4.  
  5. typedef struct W_TabView {
  6.     W_Class widgetClass;
  7.     W_View *view;
  8.  
  9.     struct W_TabViewItem **items;
  10.     int itemCount;
  11.     int maxItems;           /* size of items array, can be increased */
  12.  
  13.     int selectedItem;
  14.     int firstVisible;
  15.     
  16.     int visibleTabs;
  17.  
  18.     WMFont *font;
  19.  
  20.     WMColor *lightGray;
  21.     WMColor *tabColor;
  22.  
  23.     WMTabViewDelegate *delegate;
  24.  
  25.     short tabWidth;
  26.     short tabHeight;
  27.  
  28.     struct {
  29.     WMReliefType relief:4;
  30.     WMTitlePosition titlePosition:4;
  31.     WMTabViewTypes type:2;
  32.  
  33.     unsigned tabbed:1;
  34.     unsigned dontFitAll:1;
  35.     } flags;
  36. } TabView;
  37.  
  38.  
  39.  
  40. #define DEFAULT_WIDTH    40
  41. #define DEFAULT_HEIGHT    40
  42.  
  43. #define NORMAL_SIDE_OFFSET 8
  44. #define BUTTONED_SIDE_OFFSET 20
  45.  
  46.  
  47. static void destroyTabView(TabView *tPtr);    
  48. static void paintTabView(TabView *tPtr);
  49.  
  50.  
  51. static void W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent);
  52.  
  53. static void W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect);
  54.  
  55. static void W_UnmapTabViewItem(WMTabViewItem *item);
  56.  
  57. static void W_MapTabViewItem(WMTabViewItem *item);
  58.  
  59. static WMView *W_TabViewItemView(WMTabViewItem *item);
  60.  
  61. static void recalcTabWidth(TabView *tPtr);
  62.  
  63.  
  64. static void
  65. handleEvents(XEvent *event, void *data)
  66. {
  67.     TabView *tPtr = (TabView*)data;
  68.  
  69.     CHECK_CLASS(data, WC_TabView);
  70.  
  71.     switch (event->type) {
  72.      case Expose:
  73.     if (event->xexpose.count!=0)
  74.         break;
  75.     paintTabView(tPtr);
  76.     break;
  77.  
  78.      case ButtonPress:
  79.     {
  80.         WMTabViewItem *item = WMTabViewItemAtPoint(tPtr,
  81.                                event->xbutton.x,
  82.                                event->xbutton.y);
  83.         if (item) {
  84.         WMSelectTabViewItem(tPtr, item);
  85.         } else if (tPtr->flags.dontFitAll) {
  86.         int redraw;
  87.         if (event->xbutton.x < BUTTONED_SIDE_OFFSET) {
  88.             if (tPtr->firstVisible > 0) {
  89.             redraw = 1;
  90.             tPtr->firstVisible--;
  91.             }
  92.         } else if (event->xbutton.x - BUTTONED_SIDE_OFFSET
  93.                > tPtr->visibleTabs*(tPtr->tabWidth-10)) {
  94.  
  95.             if (tPtr->firstVisible + tPtr->visibleTabs
  96.             < tPtr->itemCount) {
  97.             redraw = 1;
  98.             tPtr->firstVisible++;
  99.             }
  100.         }
  101.  
  102.         if (redraw) {
  103.             paintTabView(tPtr);
  104.         }
  105.         }
  106.     }
  107.     break;
  108.  
  109.      case DestroyNotify:
  110.     destroyTabView(tPtr);
  111.     break;
  112.     }
  113. }
  114.  
  115.  
  116.  
  117. WMTabView*
  118. WMCreateTabView(WMWidget *parent)
  119. {
  120.     TabView *tPtr;
  121.     WMScreen *scr = WMWidgetScreen(parent);
  122.  
  123.     tPtr = wmalloc(sizeof(TabView));
  124.     memset(tPtr, 0, sizeof(TabView));
  125.  
  126.     tPtr->widgetClass = WC_TabView;
  127.  
  128.     tPtr->view = W_CreateView(W_VIEW(parent));
  129.     if (!tPtr->view) {
  130.     wfree(tPtr);
  131.     return NULL;
  132.     }
  133.     tPtr->view->self = tPtr;
  134.  
  135.     tPtr->lightGray = WMCreateRGBColor(scr, 0xd9d9, 0xd9d9, 0xd9d9, False);
  136.     tPtr->tabColor = WMCreateRGBColor(scr, 0x8420, 0x8420, 0x8420, False);
  137.  
  138.     tPtr->font = WMRetainFont(scr->normalFont);
  139.  
  140.     WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
  141.              |ButtonPressMask, handleEvents, tPtr);
  142.  
  143.     WMResizeWidget(tPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
  144.  
  145.     tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
  146.  
  147.     return tPtr;
  148. }
  149.  
  150.  
  151. void
  152. WMSetTabViewDelegate(WMTabView *tPtr, WMTabViewDelegate *delegate)
  153. {
  154.     tPtr->delegate = delegate;
  155. }
  156.  
  157.  
  158. void
  159. WMAddItemInTabView(WMTabView *tPtr, WMTabViewItem *item)
  160. {
  161.     WMInsertItemInTabView(tPtr, tPtr->itemCount, item);
  162. }
  163.  
  164.  
  165. void
  166. WMInsertItemInTabView(WMTabView *tPtr, int index, WMTabViewItem *item)
  167. {
  168.     wassertr(W_TabViewItemView(item) != NULL);
  169.  
  170.     if (tPtr->maxItems == tPtr->itemCount) {
  171.     WMTabViewItem **items;
  172.  
  173.     items = wrealloc(tPtr->items,
  174.              sizeof(WMTabViewItem*) * (tPtr->maxItems + 10));
  175.     memset(&items[tPtr->maxItems], 0, sizeof(WMTabViewItem*) * 10);
  176.     tPtr->items = items;
  177.     tPtr->maxItems += 10;
  178.     }
  179.  
  180.     if (index > tPtr->itemCount)
  181.     index = tPtr->itemCount;
  182.  
  183.     if (index == 0 && tPtr->items[0]) {
  184.     W_UnmapTabViewItem(tPtr->items[0]);
  185.     }
  186.  
  187.     if (index < tPtr->itemCount) {
  188.     memmove(&tPtr->items[index + 1], &tPtr->items[index],
  189.         tPtr->itemCount - index);
  190.     }
  191.  
  192.     tPtr->items[index] = item;
  193.  
  194.     tPtr->itemCount++;
  195.  
  196.     recalcTabWidth(tPtr);
  197.  
  198.     W_SetTabViewItemParent(item, tPtr);
  199.  
  200.     W_UnmapTabViewItem(item);
  201.  
  202.     W_ReparentView(W_TabViewItemView(item), tPtr->view, 1, 
  203.            tPtr->tabHeight + 1);
  204.  
  205.     W_ResizeView(W_TabViewItemView(item), tPtr->view->size.width - 3,
  206.          tPtr->view->size.height - tPtr->tabHeight - 3);
  207.  
  208.     if (index == 0) {
  209.     W_MapTabViewItem(item);
  210.     }
  211.     if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
  212.     (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
  213. }
  214.  
  215.  
  216. void
  217. WMRemoveTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
  218. {
  219.     int i;
  220.  
  221.     for (i = 0; i < tPtr->itemCount; i++) {
  222.     if (tPtr->items[i] == item) {
  223.         if (i < tPtr->itemCount - 1)
  224.         memmove(&tPtr->items[i], &tPtr->items[i + 1],
  225.             tPtr->itemCount - i - 1);
  226.         else
  227.         tPtr->items[i] = NULL;
  228.  
  229.         W_SetTabViewItemParent(item, NULL);
  230.  
  231.         tPtr->itemCount--;
  232.         break;
  233.     }
  234.     }
  235.     if (tPtr->delegate && tPtr->delegate->didChangeNumberOfItems)
  236.     (*tPtr->delegate->didChangeNumberOfItems)(tPtr->delegate, tPtr);
  237. }
  238.  
  239.  
  240.  
  241. static Bool
  242. isInside(int x, int y, int width, int height, int px, int py)
  243. {
  244.     if (py >= y + height - 3 && py <= y + height
  245.     && px >= x + py - (y + height - 3)
  246.     && px <= x + width - (py - (y + height - 3))) {
  247.  
  248.     return True;
  249.     }
  250.     if (py >= y + 3 && py < y + height - 3
  251.     && px >= x + 3 + ((y + 3) - py)*3/7
  252.     && px <= x + width - 3 - ((y + 3) - py)*3/7) {
  253.  
  254.     return True;
  255.     }
  256.     if (py >= y && py < y + 3
  257.     && px >= x + 7 + py - y
  258.     && px <= x + width - 7 - (py - y)) {
  259.  
  260.     return True;
  261.     }
  262.     return False;
  263. }
  264.  
  265.  
  266. WMTabViewItem*
  267. WMTabViewItemAtPoint(WMTabView *tPtr, int x, int y)
  268. {
  269.     int i;
  270.     int offset;
  271.     int count = tPtr->visibleTabs;
  272.     int first = tPtr->firstVisible;
  273.     
  274.     if (tPtr->flags.dontFitAll) {
  275.     offset = BUTTONED_SIDE_OFFSET;
  276.  
  277.     i = tPtr->selectedItem - tPtr->firstVisible;
  278.     if (i >= 0 && i < tPtr->visibleTabs
  279.         && isInside(offset + (tPtr->tabWidth-10)*i, 0, tPtr->tabWidth,
  280.             tPtr->tabHeight, x, y)) {
  281.         return tPtr->items[tPtr->selectedItem];
  282.     }
  283.     } else {
  284.     offset = NORMAL_SIDE_OFFSET;
  285.  
  286.     i = tPtr->selectedItem;
  287.     if (isInside(offset + (tPtr->tabWidth-10)*i, 0, tPtr->tabWidth,
  288.              tPtr->tabHeight, x, y)) {
  289.         return tPtr->items[i];
  290.     }
  291.     }
  292.  
  293.     for (i = 0; i < count; i++) {
  294.     if (isInside(offset + (tPtr->tabWidth-10)*i, 0, tPtr->tabWidth,
  295.              tPtr->tabHeight, x, y)) {
  296.         return tPtr->items[i+first];
  297.     }
  298.     }
  299.     return NULL;
  300. }
  301.  
  302.  
  303. void
  304. WMSelectFirstTabViewItem(WMTabView *tPtr)
  305. {
  306.     WMSelectTabViewItemAtIndex(tPtr, 0);
  307. }
  308.  
  309.  
  310. void
  311. WMSelectLastTabViewItem(WMTabView *tPtr)
  312. {
  313.     WMSelectTabViewItemAtIndex(tPtr, tPtr->itemCount);
  314. }
  315.  
  316.  
  317. void
  318. WMSelectNextTabViewItem(WMTabView *tPtr)
  319. {
  320.     WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem + 1);
  321. }
  322.  
  323.  
  324. void
  325. WMSelectPreviousTabViewItem(WMTabView *tPtr)
  326. {
  327.     WMSelectTabViewItemAtIndex(tPtr, tPtr->selectedItem - 1);
  328. }
  329.  
  330.  
  331. WMTabViewItem*
  332. WMGetSelectedTabViewItem(WMTabView *tPtr)
  333. {
  334.     return tPtr->items[tPtr->selectedItem];
  335. }
  336.  
  337.  
  338. void
  339. WMSelectTabViewItem(WMTabView *tPtr, WMTabViewItem *item)
  340. {
  341.     int i;
  342.  
  343.     for (i = 0; i < tPtr->itemCount; i++) {
  344.     if (tPtr->items[i] == item) {
  345.         WMSelectTabViewItemAtIndex(tPtr, i);
  346.         break;
  347.     }
  348.     }
  349. }
  350.  
  351.  
  352. void
  353. WMSelectTabViewItemAtIndex(WMTabView *tPtr, int index)
  354. {
  355.     WMTabViewItem *item;
  356.  
  357.     if (index == tPtr->selectedItem)
  358.     return;
  359.  
  360.     if (index < 0)
  361.     index = 0;
  362.     else if (index >= tPtr->itemCount)
  363.     index = tPtr->itemCount - 1;
  364.  
  365.     item = tPtr->items[tPtr->selectedItem];
  366.  
  367.     if (tPtr->delegate && tPtr->delegate->shouldSelectItem)
  368.     if (!(*tPtr->delegate->shouldSelectItem)(tPtr->delegate, tPtr, 
  369.                          tPtr->items[index]))
  370.         return;
  371.  
  372.     if (tPtr->delegate && tPtr->delegate->willSelectItem)
  373.     (*tPtr->delegate->willSelectItem)(tPtr->delegate, tPtr, 
  374.                       tPtr->items[index]);
  375.  
  376.     W_UnmapTabViewItem(item);
  377.  
  378.  
  379.     item = tPtr->items[index];
  380.  
  381.     W_MapTabViewItem(item);
  382.  
  383.     tPtr->selectedItem = index;
  384.  
  385.     if (tPtr->delegate && tPtr->delegate->didSelectItem)
  386.     (*tPtr->delegate->didSelectItem)(tPtr->delegate, tPtr, 
  387.                      tPtr->items[index]);
  388. }
  389.  
  390.  
  391. static void
  392. recalcTabWidth(TabView *tPtr)
  393. {
  394.     int i;
  395.     int twidth = W_VIEW(tPtr)->size.width;
  396.     int width;
  397.  
  398.     tPtr->tabWidth = 0;
  399.     for (i = 0; i < tPtr->itemCount; i++) {
  400.     char *str = WMGetTabViewItemLabel(tPtr->items[i]);
  401.  
  402.     if (str) {
  403.         width = WMWidthOfString(tPtr->font, str, strlen(str));
  404.         if (width > tPtr->tabWidth)
  405.         tPtr->tabWidth = width;
  406.     }
  407.     }
  408.     tPtr->tabWidth += 30;
  409.     if ((tPtr->tabWidth + 2) * tPtr->itemCount > twidth - 2*NORMAL_SIDE_OFFSET) {
  410.     tPtr->flags.dontFitAll = 1;
  411.     tPtr->firstVisible = 0;
  412.     tPtr->visibleTabs = (twidth - 2*BUTTONED_SIDE_OFFSET) / (tPtr->tabWidth-10);
  413.     } else {
  414.     tPtr->flags.dontFitAll = 0;
  415.     tPtr->firstVisible = 0;
  416.     tPtr->visibleTabs = tPtr->itemCount;
  417.     }
  418. }
  419.  
  420.  
  421. static void
  422. drawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
  423.        unsigned int height)
  424. {
  425.     Display *dpy = scr->display;
  426.     GC bgc = WMColorGC(scr->black);
  427.     GC wgc = WMColorGC(scr->white);
  428.     GC dgc = WMColorGC(scr->darkGray);
  429.  
  430.     XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
  431.  
  432.     XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
  433.     XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
  434.  
  435.     XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
  436.     XDrawLine(dpy, d, dgc, x+width-2, y+1, x+width-2, y+height-2);
  437. }
  438.  
  439.  
  440. static void
  441. drawTab(TabView *tPtr, Drawable d, int x, int y, 
  442.     unsigned width, unsigned height, Bool selected)
  443. {
  444.     WMScreen *scr = W_VIEW(tPtr)->screen;
  445.     Display *dpy = scr->display;
  446.     GC white = WMColorGC(selected ? scr->white : tPtr->lightGray);
  447.     GC black = WMColorGC(scr->black);
  448.     GC dark = WMColorGC(scr->darkGray);
  449.     GC light = WMColorGC(scr->gray);
  450.     XPoint trap[8];
  451.  
  452.     trap[0].x = x + (selected ? 0 : 1);
  453.     trap[0].y = y + height - (selected ? 0 : 1);
  454.  
  455.     trap[1].x = x + 3;
  456.     trap[1].y = y + height - 3;
  457.  
  458.     trap[2].x = x + 10 - 3;
  459.     trap[2].y = y + 3;
  460.  
  461.     trap[3].x = x + 10;
  462.     trap[3].y = y;
  463.  
  464.     trap[4].x = x + width - 10;
  465.     trap[4].y = y;
  466.  
  467.     trap[5].x = x + width - 10 + 3;
  468.     trap[5].y = y + 3;
  469.  
  470.     trap[6].x = x + width - 3;
  471.     trap[6].y = y + height - 3;
  472.  
  473.     trap[7].x = x + width - (selected ? 0 : 1);
  474.     trap[7].y = y + height - (selected ? 0 : 1);
  475.  
  476.     XFillPolygon(dpy, d, selected ? light : WMColorGC(tPtr->tabColor), trap, 8,
  477.          Convex, CoordModeOrigin);
  478.  
  479.     XDrawLine(dpy, d, white, trap[0].x, trap[0].y, trap[1].x, trap[1].y);
  480.     XDrawLine(dpy, d, white, trap[1].x, trap[1].y, trap[2].x, trap[2].y);
  481.     XDrawLine(dpy, d, white, trap[2].x, trap[2].y, trap[3].x, trap[3].y);
  482.     XDrawLine(dpy, d, white, trap[3].x, trap[3].y, trap[4].x, trap[4].y);
  483.     XDrawLine(dpy, d, dark, trap[4].x, trap[4].y, trap[5].x, trap[5].y);
  484.     XDrawLine(dpy, d, black, trap[5].x, trap[5].y, trap[6].x, trap[6].y);
  485.     XDrawLine(dpy, d, black, trap[6].x, trap[6].y, trap[7].x, trap[7].y);
  486.  
  487.     XDrawLine(dpy, d, selected ? light : WMColorGC(scr->white), 
  488.           trap[0].x, trap[0].y, trap[7].x, trap[7].y);
  489. }
  490.  
  491.  
  492. static void
  493. paintDot(TabView *tPtr, Drawable d, int x, int y)
  494. {
  495.     WMScreen *scr = W_VIEW(tPtr)->screen;
  496.     Display *dpy = scr->display;
  497.     GC white = WMColorGC(scr->white);
  498.     GC black = WMColorGC(scr->black);
  499.  
  500.     XFillRectangle(dpy, d, black, x, y, 2, 2);
  501.     XDrawPoint(dpy, d, white, x, y);
  502. }
  503.  
  504.  
  505.  
  506. static void
  507. paintTabView(TabView *tPtr)
  508. {
  509.     Pixmap buffer;
  510.     WMScreen *scr = W_VIEW(tPtr)->screen;
  511.     Display *dpy = scr->display;
  512.     GC white = WMColorGC(scr->white);
  513.     int i;
  514.     WMRect rect;
  515.  
  516.     if (tPtr->flags.type == WTTopTabsBevelBorder) {
  517.     int count = tPtr->visibleTabs;
  518.     int first = tPtr->firstVisible;
  519.     int offs;
  520.     int moreAtLeft;
  521.     int moreAtRight;
  522.     int selectedIsVisible;
  523.     
  524.     buffer = XCreatePixmap(dpy, W_VIEW(tPtr)->window,
  525.                    W_VIEW(tPtr)->size.width, tPtr->tabHeight,
  526.                    W_VIEW(tPtr)->screen->depth);
  527.  
  528.     XFillRectangle(dpy, buffer, WMColorGC(W_VIEW(tPtr)->backColor),
  529.                0, 0, W_VIEW(tPtr)->size.width, tPtr->tabHeight);
  530.  
  531.     rect.pos.y = 2;
  532.     if (tPtr->flags.dontFitAll) {
  533.         rect.pos.x = 15 + BUTTONED_SIDE_OFFSET;
  534.         offs = BUTTONED_SIDE_OFFSET;
  535.         moreAtLeft = first > 0;
  536.         moreAtRight = (first + count) < tPtr->itemCount;
  537.         if (tPtr->selectedItem >= first
  538.         && tPtr->selectedItem < first + count)
  539.         selectedIsVisible = 1;
  540.         else
  541.         selectedIsVisible = 0;
  542.     } else {
  543.         rect.pos.x = 15 + NORMAL_SIDE_OFFSET;
  544.         offs = NORMAL_SIDE_OFFSET;
  545.         moreAtLeft = 0;
  546.         moreAtRight = 0;
  547.         selectedIsVisible = 1;
  548.     }
  549.     rect.size.width = tPtr->tabWidth;
  550.     rect.size.height = tPtr->tabHeight;
  551.  
  552.     for (i = count - (moreAtRight ? 0 : 1);
  553.          i >= (moreAtLeft ? -1 : 0); i--) {
  554.         if (!selectedIsVisible || i != (tPtr->selectedItem-first)) {
  555.         drawTab(tPtr, buffer, offs + (rect.size.width-10)*i, 0,
  556.             rect.size.width, rect.size.height, False);
  557.         }
  558.     }
  559.     
  560.     if (selectedIsVisible) {
  561.         drawTab(tPtr, buffer, 
  562.             offs + (rect.size.width-10) * (tPtr->selectedItem - first),
  563.             0, rect.size.width, rect.size.height, True);
  564.  
  565.         XDrawLine(dpy, buffer, white, 0, tPtr->tabHeight - 1,
  566.               offs, tPtr->tabHeight - 1);
  567.  
  568.         XDrawLine(dpy, buffer, white, 
  569.               offs + 10 + (rect.size.width-10) * count,
  570.               tPtr->tabHeight - 1, W_VIEW(tPtr)->size.width - 1,
  571.               tPtr->tabHeight - 1);
  572.     } else {
  573.         XDrawLine(dpy, buffer, white, 0, tPtr->tabHeight - 1,
  574.               W_VIEW(tPtr)->size.width, tPtr->tabHeight - 1);        
  575.     }
  576.  
  577.     for (i = 0; i < count; i++) {
  578.         W_DrawLabel(tPtr->items[first+i], buffer, rect);
  579.  
  580.         rect.pos.x += rect.size.width - 10;
  581.     }
  582.  
  583.     if (moreAtLeft) {
  584.         paintDot(tPtr, buffer, 4, 10);
  585.         paintDot(tPtr, buffer, 7, 10);
  586.         paintDot(tPtr, buffer, 10, 10);
  587.     }
  588.     if (moreAtRight) {
  589.         int x;
  590.         
  591.         x = BUTTONED_SIDE_OFFSET - 5 + tPtr->visibleTabs * (tPtr->tabWidth - 10);
  592.         
  593.         x = x + (W_VIEW(tPtr)->size.width - x)/2;
  594.         
  595.         paintDot(tPtr, buffer, x + 5, 10);
  596.         paintDot(tPtr, buffer, x + 8, 10);
  597.         paintDot(tPtr, buffer, x + 11, 10);        
  598.     }
  599.  
  600.     XCopyArea(dpy, buffer, W_VIEW(tPtr)->window, scr->copyGC, 0, 0,
  601.           W_VIEW(tPtr)->size.width, tPtr->tabHeight, 0, 0);
  602.  
  603.     XFreePixmap(dpy, buffer);
  604.     }
  605.     switch (tPtr->flags.type) {
  606.      case WTTopTabsBevelBorder:
  607.     drawRelief(scr, W_VIEW(tPtr)->window, 0, tPtr->tabHeight - 1,
  608.            W_VIEW(tPtr)->size.width,
  609.            W_VIEW(tPtr)->size.height - tPtr->tabHeight + 1);
  610.     break;
  611.  
  612.      case WTNoTabsBevelBorder:
  613.     W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
  614.              W_VIEW(tPtr)->size.height, WRRaised);
  615.     break;
  616.  
  617.      case WTNoTabsLineBorder:
  618.     W_DrawRelief(scr, W_VIEW(tPtr)->window, 0, 0, W_VIEW(tPtr)->size.width,
  619.              W_VIEW(tPtr)->size.height, WRSimple);
  620.     break;
  621.  
  622.      case WTNoTabsNoBorder:
  623.     break;
  624.     }
  625. }
  626.  
  627.  
  628. static void
  629. destroyTabView(TabView *tPtr)
  630. {
  631.     int i;
  632.  
  633.     for (i = 0; i < tPtr->itemCount; i++) {
  634.     WMSetTabViewItemView(tPtr->items[i], NULL);
  635.     WMDestroyTabViewItem(tPtr->items[i]);
  636.     }
  637.     wfree(tPtr->items);
  638.  
  639.     WMReleaseColor(tPtr->lightGray);
  640.     WMReleaseColor(tPtr->tabColor);
  641.     WMReleaseFont(tPtr->font);
  642.  
  643.     wfree(tPtr);
  644. }
  645.  
  646. /******************************************************************/
  647.  
  648.  
  649. typedef struct W_TabViewItem {
  650.     WMTabView *tabView;
  651.  
  652.     W_View *view;
  653.  
  654.     char *label;
  655.  
  656.     int identifier;
  657.  
  658.     struct {
  659.     unsigned visible:1;
  660.     } flags;
  661. } TabViewItem;
  662.  
  663.  
  664. static void
  665. W_SetTabViewItemParent(WMTabViewItem *item, WMTabView *parent)
  666. {
  667.     item->tabView = parent;
  668. }
  669.  
  670.  
  671. static void
  672. W_DrawLabel(WMTabViewItem *item, Drawable d, WMRect rect)
  673. {
  674.     WMScreen *scr = W_VIEW(item->tabView)->screen;
  675.  
  676.     if (!item->label)
  677.     return;
  678.  
  679.     WMDrawString(scr, d, WMColorGC(scr->black), item->tabView->font,
  680.          rect.pos.x, rect.pos.y, item->label, strlen(item->label));
  681. }
  682.  
  683.  
  684. static void
  685. W_UnmapTabViewItem(WMTabViewItem *item)
  686. {
  687.     wassertr(item->view);
  688.  
  689.     W_UnmapView(item->view);
  690.  
  691.     item->flags.visible = 0;
  692. }
  693.  
  694.  
  695. static void
  696. W_MapTabViewItem(WMTabViewItem *item)
  697. {
  698.     wassertr(item->view);
  699.  
  700.     W_MapView(item->view);
  701.  
  702.     item->flags.visible = 1;
  703. }
  704.  
  705.  
  706. static WMView*
  707. W_TabViewItemView(WMTabViewItem *item)
  708. {
  709.     return item->view;
  710. }
  711.  
  712.  
  713. WMTabViewItem*
  714. WMCreateTabViewItemWithIdentifier(int identifier)
  715. {
  716.     WMTabViewItem *item;
  717.  
  718.     item = wmalloc(sizeof(WMTabViewItem));
  719.     memset(item, 0, sizeof(WMTabViewItem));
  720.  
  721.     item->identifier = identifier;
  722.  
  723.     return item;
  724. }
  725.  
  726.  
  727. int
  728. WMGetTabViewItemIdentifier(WMTabViewItem *item)
  729. {
  730.     return item->identifier;
  731. }
  732.  
  733.  
  734. void
  735. WMSetTabViewFont(WMTabView *tPtr, WMFont *font)
  736. {
  737.     if (tPtr->font)
  738.     WMReleaseFont(tPtr->font);
  739.  
  740.     tPtr->font = WMRetainFont(font);
  741.     tPtr->tabHeight = WMFontHeight(tPtr->font) + 3;
  742.     recalcTabWidth(tPtr);
  743. }
  744.  
  745.  
  746. void
  747. WMSetTabViewItemLabel(WMTabViewItem *item, char *label)
  748. {
  749.     if (item->label)
  750.     wfree(item->label);
  751.  
  752.     item->label = wstrdup(label);
  753.  
  754.     if (item->tabView)
  755.     recalcTabWidth(item->tabView);
  756. }
  757.  
  758.  
  759. char*
  760. WMGetTabViewItemLabel(WMTabViewItem *item)
  761. {
  762.     return item->label;
  763. }
  764.  
  765.  
  766. void
  767. WMSetTabViewItemView(WMTabViewItem *item, WMView *view)
  768. {
  769.     item->view = view;
  770. }
  771.  
  772.  
  773. WMView*
  774. WMGetTabViewItemView(WMTabViewItem *item)
  775. {
  776.     return item->view;
  777. }
  778.  
  779.  
  780. void
  781. WMDestroyTabViewItem(WMTabViewItem *item)
  782. {
  783.     if (item->label)
  784.     wfree(item->label);
  785.  
  786.     if (item->view)
  787.     W_DestroyView(item->view);
  788.  
  789.     wfree(item);
  790. }
  791.